#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import os
from minio import Minio
from minio.error import S3Error
from io import BytesIO

# 公共访问 URL 前缀，比如 nginx 或 MinIO 绑定的域名
PUBLIC_URL = "https://minapi.huaxianguan.com"  # 或者 https://minapi.huaxianguan.com

endpoint = "minapi.huaxianguan.com"
access_key = "admin"
secret_key = "admin123456"


class MinioClient:
    """
    MinIO 客户端，上传完直接返回公网访问 URL
    """

    def __init__(self, endpoint, access_key, secret_key, bucket_name, secure=False):
        self.client = Minio(endpoint, access_key=access_key, secret_key=secret_key, secure=secure)
        self.bucket_name = bucket_name
        if not self.client.bucket_exists(bucket_name):
            self.client.make_bucket(bucket_name)

    # ================= 上传文件 =================
    def upload_file(self, object_name, file_path, content_type=None) -> str:
        """上传文件并返回公网 URL"""
        try:
            self.client.fput_object(self.bucket_name, object_name, file_path, content_type=content_type)
            return f"{PUBLIC_URL}/{self.bucket_name}/{object_name}"
        except S3Error as e:
            raise RuntimeError(f"上传文件失败: {e}")

    def upload_bytes(self, object_name, data: bytes, content_type="application/octet-stream") -> str:
        """上传二进制数据并返回公网 URL"""
        try:
            self.client.put_object(
                self.bucket_name, object_name, BytesIO(data), length=len(data), content_type=content_type
            )
            return f"{PUBLIC_URL}/{self.bucket_name}/{object_name}"
        except S3Error as e:
            raise RuntimeError(f"上传字节数据失败: {e}")

    def upload_folder(self, local_folder, remote_folder="") -> dict:
        """
        上传目录，返回 dict {object_name: 公网 URL}
        """
        if not os.path.isdir(local_folder):
            raise ValueError(f"{local_folder} 不是目录")
        urls = {}
        for root, _, files in os.walk(local_folder):
            for file in files:
                local_path = os.path.join(root, file)
                relative_path = os.path.relpath(local_path, local_folder)
                object_name = os.path.join(remote_folder, relative_path).replace("\\", "/")
                url = self.upload_file(object_name, local_path)
                urls[object_name] = url
        return urls

    # ================= 下载 / 删除 / 列举 =================
    def download_file(self, object_name, file_path):
        try:
            self.client.fget_object(self.bucket_name, object_name, file_path)
        except S3Error as e:
            raise RuntimeError(f"下载失败: {e}")

    def download_bytes(self, object_name) -> bytes:
        try:
            response = self.client.get_object(self.bucket_name, object_name)
            data = response.read()
            response.close()
            response.release_conn()
            return data
        except S3Error as e:
            raise RuntimeError(f"下载失败: {e}")

    def delete_object(self, object_name):
        try:
            self.client.remove_object(self.bucket_name, object_name)
        except S3Error as e:
            raise RuntimeError(f"删除失败: {e}")

    def list_objects(self, prefix="", recursive=True):
        try:
            return [obj.object_name for obj in self.client.list_objects(self.bucket_name, prefix=prefix, recursive=recursive)]
        except S3Error as e:
            raise RuntimeError(f"列举对象失败: {e}")


# ================= 示例 =================
if __name__ == "__main__":
    minio_client = MinioClient(endpoint, access_key, secret_key, bucket_name="anmo", secure=False)

    # 上传单文件
    url = minio_client.upload_file("tests/minio_client.py", "minio_client.py")
    print("单文件 URL:", url)

    # 上传二进制
    url2 = minio_client.upload_bytes("tests/hello.txt", b"hello minio!")
    print("二进制文件 URL:", url2)

    # 上传目录
    urls = minio_client.upload_folder(os.getcwd(), "remote_folder")
    print("文件夹上传 URL:", urls)
